package csel.controller;

import java.awt.event.ActionEvent;

import junit.framework.Assert;
import junit.framework.TestCase;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import csel.controller.commands.*;
import csel.controller.dispatchers.ModelDispatcher;
import csel.controller.listeners.*;
import csel.model.GameCommand;
import csel.model.Model;

public class TestDispatchQueue extends TestCase
{
	// Get a dummy view
	TestControllerWithViewDummy t;

	// run the test
	public static void main(String args[])
	{
		junit.textui.TestRunner.run(TestDispatchQueue.class);
	}

	// @Test
	// public void testModelDispatcherQueue() throws InterruptedException
	// {
	// // create Controller, threads, dummy view
	// t = TestControllerWithViewDummy.newInstance();
	// t.makeView();
	// ModelDispatcher ad =
	// (ModelDispatcher)t.getControllerBuilder().getModelDispatcher();
	//          
	// /**********************************************
	// * YOU HAVE 5 SECONDS TO CLICK IN THE WINDOW!!!
	// *
	// * DO SOMETHING!!!
	// */
	// Thread.currentThread().sleep(5000);
	//
	// // when that's over, there should be commands in the queue
	// Assert.assertFalse(ad.isEmpty());
	// t.destroy();
	// }

	@Test
	public void testButtonPressDispatch() throws InterruptedException
	{
		// ****** TEST FOR '1' KEY ******
		Assert.assertEquals(new Character('1'), testKeyPress('1'));

		// ****** TEST FOR '2' KEY ******
		Assert.assertEquals(new Character('2'), testKeyPress('2'));

		// ****** TEST FOR '3' KEY ******
		Assert.assertEquals(new Character('3'), testKeyPress('3'));

		// ****** TEST FOR '4' KEY ******
		Assert.assertEquals(new Character('4'), testKeyPress('4'));

		// ****** TEST FOR '6' KEY ******
		Assert.assertEquals(new Character('6'), testKeyPress('6'));

		// ****** TEST FOR '7' KEY ******
		Assert.assertEquals(new Character('7'), testKeyPress('7'));

		// ****** TEST FOR '8' KEY ******
		Assert.assertEquals(new Character('8'), testKeyPress('8'));

		// ****** TEST FOR '9' KEY ******
		Assert.assertEquals(new Character('9'), testKeyPress('9'));
	}

	public Character testKeyPress(Character c) throws InterruptedException
	{
		// create Controller, threads, dummy view
		t = TestControllerWithViewDummy.newInstance();
		t.makeView();
//		ModelDispatcher ad = (ModelDispatcher) t.getControllerBuilder()
//				.getModelDispatcher();
//		Model md = (ModelDummy) t.getModel();
//		t.getControllerBuilder().getModelDispatcher().killWorker();
//		t.getControllerBuilder().getViewDispatcher().killWorker();
//
//		System.out.println("[JUNIT] ***** PRESS " + c.charValue() + " *****");
//
//		// when that's over, there should be commands in the queue
//		// thread will wait when queue is empty
//		ad.dispatchCommand();
//		MoveCommand mc = (MoveCommand) ((ModelDummy)md).getBla();
//
//		t.destroy();
//		Thread.sleep(300);
//		return mc.getValue();
		return '1';
	}

	@Test
	public void testKeyPressWithoutManualDispatch() throws InterruptedException
	{
		// create Controller, threads, dummy view
		t = TestControllerWithViewDummy.newInstance();
		t.makeView();
		Model md = (ModelDummy) t.getModel();

		System.out.println("[JUNIT] ***** PRESS and Movement key *****");
		Thread.sleep(3000);
		// when that's over, there should be commands in the queue
		// thread will wait when queue is empty
		GameCommand gc = ((ModelDummy)md).getBla();
		if (gc instanceof StopCommand)
		{
			Assert
					.assertEquals(new StopCommand(null).getClass(), gc
							.getClass());
		} else if (gc instanceof MoveCommand)
		{
			Assert.assertEquals(new MoveCommand(null, null).getClass(), gc
					.getClass());
		} else
		{
			Assert.fail("Movement key was not pressed in the last three seconds");
		}
		t.destroy();
	}

	@Test
	public void testButtonPressQDispatch() throws InterruptedException
	{
		t = TestControllerWithViewDummy.newInstance();
		t.makeView();
		t.getControllerBuilder().getModelDispatcher().killWorker();
		t.getControllerBuilder().getViewDispatcher().killWorker();
		ModelDispatcher ad = (ModelDispatcher) t.getControllerBuilder()
				.getModelDispatcher();

		System.out.println("[JUNIT] ***** PRESS q, muthafucka! *****");

		// thread will wait when queue is empty
		ad.dispatchCommand();

		// when that's over, there should be commands in the queue
		QuitCommand qc = new QuitCommand(null, null, null, null);
		Model md = (ModelDummy) t.getModel();
		Assert.assertEquals(qc.getClass(), ((ModelDummy)md).getBla());
		t.destroy();
	}
//
//	@Test
//	public void testKeyPressFive() throws InterruptedException
//	{
//		// create Controller, threads, dummy view
//		t = TestControllerWithViewDummy.newInstance();
//		t.makeView();
//		ModelDispatcher ad = (ModelDispatcher) t.getControllerBuilder()
//				.getModelDispatcher();
//		Model md = (Model) t.getModel();
//		t.getControllerBuilder().getModelDispatcher().killWorker();
//		t.getControllerBuilder().getViewDispatcher().killWorker();
//
//		System.out.println("[JUNIT] ***** PRESS 5 *****");
//
//		Thread.sleep(3000);
//		// when that's over, there should be commands in the queue
//		// thread will wait when queue is empty
//		MoveCommand mc = (MoveCommand) md.getBla();
//
//		t.destroy();
//		Thread.sleep(300);
//		Assert.assertTrue(ad.isEmpty());
//	}

	@Test
	public void testAllActionEventDispatches() throws InterruptedException
	{
		testStatusActionDispatch("drop", new DropCommand(null, null));
		testStatusActionDispatch("use", new UseCommand(null, null));
		testStatusActionDispatch("equip", new EquipCommand(null, null));
		testStatusActionDispatch("unequip", new UnequipCommand(null, null));
		testStatusActionDispatch("quit", new QuitCommand(null, null, null, null));
//		testStatusActionDispatch("load", new LoadCommand(null, null));
		testStatusActionDispatch("save", new SaveCommand(null, null));
//		testStatusActionDispatch("new", new NewCommand(null, null));
	}

	public void testStatusActionDispatch(String s, GameCommand gc)
			throws InterruptedException
	{
		t = TestControllerWithViewDummy.newInstance();
		t.makeView();
		t.getControllerBuilder().getModelDispatcher().killWorker();
		t.getControllerBuilder().getViewDispatcher().killWorker();
		ModelDispatcher ad = (ModelDispatcher) t.getControllerBuilder()
				.getModelDispatcher();

		System.out.println("[JUNIT] ***** PRESS " + s + " *****");

		ActionEvent ac = new ActionEvent(t.statusViewport, 1, s);
		StatusViewActionListener al = t.getStatusListener();
		al.actionPerformed(ac);

		ad.dispatchCommand();
		Model md = (ModelDummy) t.getModel();
		Assert.assertEquals(gc.getClass(), ((ModelDummy)md).getBla());
		t.destroy();
	}

	@Test
	public void testAllActionEventDispatchesWithoutManualDispatch()
			throws InterruptedException
	{
		testStatusActionDispatchWithoutManualDispatch("drop", new DropCommand(
				null, null));
		testStatusActionDispatchWithoutManualDispatch("use", new UseCommand(
				null, null));
		testStatusActionDispatchWithoutManualDispatch("equip",
				new EquipCommand(null, null));
		testStatusActionDispatchWithoutManualDispatch("unequip",
				new UnequipCommand(null, null));
		testStatusActionDispatchWithoutManualDispatch("quit", new QuitCommand(
				null, null, null, null));
//		testStatusActionDispatchWithoutManualDispatch("load", new LoadCommand(
//				null, null));
//		testStatusActionDispatchWithoutManualDispatch("save", new SaveCommand(
//				null, null));
//		testStatusActionDispatchWithoutManualDispatch("new", new NewCommand(
//				null, null));
	}

	public void testStatusActionDispatchWithoutManualDispatch(String s,
			GameCommand gc) throws InterruptedException
	{
		t = TestControllerWithViewDummy.newInstance();
		t.makeView();

		System.out.println("[JUNIT] ***** PRESS " + s + " *****");

		ActionEvent ac = new ActionEvent(t.statusViewport, 1, s);
		StatusViewActionListener al = t.getStatusListener();
		al.actionPerformed(ac);

		Thread.sleep(300);
		Model md = (ModelDummy) t.getModel();
		Assert.assertEquals(gc.getClass(), ((ModelDummy)md).getBla());
		t.destroy();
	}

	@Before
	protected void setup() throws Exception
	{
		super.setUp();
	}

	@After
	protected void tearDown() throws Exception
	{
		super.tearDown();
	}
}
